class EventChannel {
    /**
     * 订阅者
     * @type { Map<string, {callback: Function, once: boolean}[]> }
    */
    #subscribers;
    // 是否只订阅一次
    #once;
    constructor({
        // 是否只订阅一次 默认一次
        once = true,
        events = new Map([])
    }) {
        this.#subscribers = new Map([...events]);
        this.#once = once;
    }
    /**
     * 订阅事件
     * @param {string} event 事件名称
     * @param {Function} callback 回调函数
     * @param {boolean} once 是否只订阅一次
    */
    on(event, callback, once = this.#once) {
        if(!this.#subscribers.has(event)) {
            this.#subscribers.set(event, []);
        }
        this.#subscribers.get(event).find(item => item.callback !== callback) || this.#subscribers.get(event).push({
            callback,
            once
        })
    }
    /**
     * 发布事件
     * @param {string} event 事件名称
     * @param  {...any} args 参数列表
    */
    emit(event, ...args) {
        if(this.#subscribers.has(event)) {
            this.#subscribers.get(event).forEach(container => container.callback(...args));
            this.offOnceFn(event)
        }
    }
    /**
     * private 清空只订阅一次的事件
     * @param {string} event 事件名称
    */
    offOnceFn(event){
        this.#subscribers.set(event, this.#subscribers.get(event).filter(container => !container.once));
        this.off(event);
    }
    /**
     * 销毁某个订阅者中的某个事件对象
     * @param {string} event 事件名称
     * @param {Function} container 事件对象
    */
    offFn(event, container) {
        const containers = this.#subscribers.get(event)
        if(!containers || !containers.length) return
        const index = containers.findIndex(item => item === container);
        if(index !== -1) containers.splice(index, 1);
        if(!containers.length) this.#subscribers.delete(event);
    }
    /**
     * 销毁订阅者事件列表
     * @param {string} container 事件名称
    */
    off(event) {
        if(!this.#subscribers.get(event).length) this.#subscribers.delete(event);
    }
    // 销毁所有订阅者事件列表
    offAll() {
        this.#subscribers.clear();
    }
    // 获取事件列表
    getEvent(){
        return this.#subscribers;
    }
    // 合并事件
    mergeEvent(events){
        this.#subscribers = new Map([...this.#subscribers,...events])
    }
}

export default EventChannel